﻿using Framework;
using UnityEngine;

namespace Game
{
    public class GameObjectEntity : CommonEntity
    {
        public GameObject gameObject { get; protected set; }
        public Transform transform { get; protected set; }

        protected bool _isCompleted = false;
        
        private ResourceComponent _resourceComp;
        private string _url;
        private Vector3 _cachePosition = Vector3.zero;
        private bool _isLocalPosition = true;
        private Transform _parent;

        public GameObjectEntity()
        {
            _resourceComp = AddComponent<ResourceComponent>();
            _resourceComp.Completed += OnResLoadCompleted;
        }

        public void Load(string url)
        {
            Reset();
            _url = url;
            _resourceComp.Load(_url);
        }

        public void SetLocalPosition(Vector3 position)
        {
            _cachePosition = position;
            _isLocalPosition = true;
            if (_isCompleted)
            {
                transform.localPosition = _cachePosition;
            }
        }

        public void SetPosition(Vector3 position)
        {
            _cachePosition = position;
            _isLocalPosition = false;
            if (_isCompleted)
            {
                transform.position = _cachePosition;
            }
        }

        public void SetParent(Transform parent)
        {
            _parent = parent;
            if (_isCompleted && _parent)
            {
                transform.SetParent(_parent, false);
            }
        }

        protected virtual void OnReset()
        { 
        }

        protected virtual void PreInstantiate()
        {
            OnPreInstantiateCompleted();
        }

        protected void OnPreInstantiateCompleted()
        {
            Instantiate();
        }

        protected virtual void PostInstantiate()
        {
            OnPostInstantiateCompleted();
        }

        protected void OnPostInstantiateCompleted()
        {
            _isCompleted = true;
            if (_isLocalPosition)
            {
                SetLocalPosition(_cachePosition);
            }
            else
            {
                SetPosition(_cachePosition);
            }

            SetParent(_parent);
            OnInstantiateCompleted();
            Emit(CommonEntityEvent.OnCompleted);
        }

        protected virtual void OnInstantiateCompleted()
        {
        }

        private void OnResLoadCompleted()
        {
            PreInstantiate();
        }

        private void Instantiate()
        {
            Resource mainResource = _resourceComp.GetResource(_url);
            gameObject = Object.Instantiate(mainResource.GetAsset<GameObject>());
            transform = gameObject.transform;
            PostInstantiate();
        }

        private void Reset()
        {
            OnReset();
            _isLocalPosition = false;
            _cachePosition = Vector3.zero;
            if (gameObject != null)
            {
                Object.Destroy(gameObject);
                gameObject = null;
                transform = null;
            }
            _url = null;
            _isCompleted = false;
            _resourceComp.Cancel();
        }
    }
}